package com.atguigu.filter;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.util.IpUtil;
import io.prometheus.client.Histogram;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Component
public class AccessFilter implements GlobalFilter {
    @Autowired
    private RedisTemplate redisTemplate;

    private AntPathMatcher antPathMatcher=new AntPathMatcher();

    @Value("${filter.whiteList}")
    private String filterWhiteList;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //规定接口不允许调用
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        if (antPathMatcher.match("/sku/**", path)){
            return writeDataTobrowser(exchange, RetValCodeEnum.NO_PERMISSION);
        }
        //如果用户的登陆了拿到用户id判断和该用户是否同一ip
        String userId = getUserId(request);
        //用户临时id
        String userTempId =getUserTempId(request);
        if ("-1".equals(userId)){
            return writeDataTobrowser(exchange, RetValCodeEnum.NO_PERMISSION);
        }

        //对指定的某些类(购物车//我的订单)拦截
        if (antPathMatcher.match("/order/**", path)){
            if (StringUtils.isEmpty(userId)){
                return writeDataTobrowser(exchange, RetValCodeEnum.NO_PERMISSION);
            }
        }
        //用户请求白名单
        for(String filterWhite:filterWhiteList.split(",")){
            //用户访问路径包含白名单路径，并且用户未登录
            if(path.indexOf(filterWhite)!=-1&&StringUtils.isEmpty(userId)){
                //跳转到登录页面
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.SEE_OTHER);
                response.getHeaders().set(HttpHeaders.LOCATION,"http://passport.gmall.com/login.html?originalUrl="+request.getURI());
                return response.setComplete();
            }
        }
        //把用户id保存到head中
        if (!StringUtils.isEmpty(userId)||!StringUtils.isEmpty(userTempId)){
            if(!StringUtils.isEmpty(userId)){
                //将用户id放入header当中
                request.mutate().header("userId",userId).build();
            }
            if(!StringUtils.isEmpty(userTempId)){
                request.mutate().header("userTempId",userTempId).build();
            }
            //过滤器放开拦截器 让下游请求继续执行(此时修改了exchange对像)
            return chain.filter(exchange.mutate().request(request).build());
        }
        //过滤器放开拦截器 让下游请求继续执行
        return chain.filter(exchange);
    }

    private String getUserTempId(ServerHttpRequest request) {
        //从header和cookie中拿用户的token
        List<String> headerValueList = request.getHeaders().get("userTempId");
        String userTempId=null;
        if (!CollectionUtils.isEmpty(headerValueList)){
            userTempId=headerValueList.get(0);
        }else {
            HttpCookie cookie = request.getCookies().getFirst("userTempId");
            if (cookie!=null){
                userTempId=cookie.getValue();
            }
        }
        return userTempId;
    }

    private String getUserId(ServerHttpRequest request) {
        List<String> headerValueList = request.getHeaders().get("token");
        String token=null;
        if (!CollectionUtils.isEmpty(headerValueList)){
           token = headerValueList.get(0);
        }else {
            HttpCookie cookie = request.getCookies().getFirst("token");
            if (cookie!=null){
                token=cookie.getValue();
            }
        }
        if (!StringUtils.isEmpty(token)){
            String userKey="user:login:"+token;
            String loginInfoJson = (String)redisTemplate.opsForValue().get(userKey);
            JSONObject jsonObject = JSONObject.parseObject(loginInfoJson);
            String IoginIp = jsonObject.getString("loginIp");
            String requestIoginip = IpUtil.getGatwayIpAddress(request);
            if (requestIoginip.equals(IoginIp)){
                return jsonObject.getString("userId");
            }else {
                return "-1";
            }
        }
        return null;
    }

    private Mono<Void> writeDataTobrowser(ServerWebExchange exchange, RetValCodeEnum retValCodeEnum) {
        ServerHttpResponse response = exchange.getResponse();
        RetVal<Object> retVal=RetVal.build(null, retValCodeEnum);
        //将retval转换为json字符串
        byte[] retBytes = JSONObject.toJSONString(retVal).getBytes(StandardCharsets.UTF_8);
        DataBuffer dataBuffer = response.bufferFactory().wrap(retBytes);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(dataBuffer));
    }
}













